home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EuroCD 3
/
EuroCD 3.iso
/
Programming
/
vbcc
/
supp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-06-24
|
13KB
|
417 lines
#include "supp.h"
static char FILE_[]=__FILE__;
char *typname[]={"strange","char","short","int","long","float","double","void",
"pointer","array","struct","union","enum","function"};
char *storage_class_name[]={"strange","auto","register","static","extern","typedef"};
char *ename[]={"strange","sequence","move","set+","set-","set*","set/","set%",
"set&","set^","set|","set<<","set>>","?:","lor","land","or",
"eor","and","equal","unequal","lt","le","gt","ge","lsl",
"lsr","add","sub","mul","div","mod","negate",
"not","preinc","postinc","predec","postdec","neg",
"dref-pointer","address-of","cast","call","index",
"dref-struct-pointer","dref-struct","identifier","constant",
"string","member",
"convert-char","convert-short","convert-int","convert-long",
"convert-float","convert-double","convert-void","convert-pointer",
"convert-uchar","convert-ushort","convert-uint","convert-ulong",
"address-of-array","first-element-of-array","pmult",
"allocreg","freereg","pconstant","test","label","beq","bne",
"blt","bge","ble","bgt","bra","compare","push","pop",
"address-of-struct","add-int-to-pointer","sub-int-from-pointer",
"sub-pointer-from-pointer","push-reg","pop-reg","pop-args",
"save-regs","restore-regs","identifier-label","dc","align",
"colon","get-return","set-return","move-from-reg","move-to-reg",
"nop"};
char *empty="";
zchar vchar; zuchar vuchar;
zshort vshort; zushort vushort;
zint vint; zuint vuint;
zlong vlong; zulong vulong;
zfloat vfloat; zdouble vdouble;
zpointer vpointer;
#ifndef DEBUG
int DEBUG;
#endif
int label;
int regs[MAXR+1],regused[MAXR+1];
struct Var *regsv[MAXR+1];
int goto_used;
int ic_count;
zlong max_offset;
int function_calls;
int multiple_ccs;
int lastlabel,return_label;
int only_inline;
struct IC *err_ic;
long maxoptpasses=10;
long optflags;
long inline_size=100;
long unroll_size=200;
long fp_assoc,noaliasopt;
int fline;
char errfname[FILENAME_MAX+1];
struct IC *first_ic,*last_ic;
int float_used;
/* Das haette ich gern woanders */
struct Var *vl1,*vl2,*vl3;
struct Typ *clone_typ(struct Typ *old)
/* Erzeugt Kopie eines Typs und liefert Zeiger auf Kopie. */
{
struct Typ *new;
if(!old) return(0);
new=mymalloc(TYPS);
*new=*old;
if(new->next) new->next=clone_typ(new->next);
return(new);
}
void free_IC(struct IC *p)
/* Gibt IC-Liste inkl. Typen frei. */
{
struct IC *merk;
if(DEBUG&1) printf("free_IC()\n");
while(p){
if(p->q1.am) free(p->q1.am);
if(p->q2.am) free(p->q2.am);
if(p->z.am) free(p->z.am);
merk=p->next;
free(p);
p=merk;
}
}
void remove_IC(struct IC *p)
/* Entfernt IC p aus Liste. */
{
if(p->prev) p->prev->next=p->next; else first_ic=p->next;
if(p->next) p->next->prev=p->prev; else last_ic=p->prev;
if(p->q1.am) free(p->q1.am);
if(p->q2.am) free(p->q2.am);
if(p->z.am) free(p->z.am);
free(p);
}
void freetyp(struct Typ *p)
/* Gibt eine Typ-Liste frei, aber keine struct_declaration oder so. */
{
int f;struct Typ *merk;
if(DEBUG&8){printf("freetyp: ");prd(stdout,p);printf("\n");}
while(p){
merk=p->next;
f=p->flags&NQ;
if(merk&&f!=ARRAY&&f!=POINTER&&f!=FUNKT){ierror(0);return;}
free(p);
p=merk;
}
}
zlong falign(struct Typ *t)
/* Liefert Alignment eines Typs. Funktioniert im Gegensatz zum */
/* align[]-Array auch mit zusammengesetzten Typen. */
{
int i,f; zlong al,alt;
f=t->flags&NQ;
al=align[f];
if(f<=POINTER) return al;
if(f==ARRAY){
do{
t=t->next;
f=t->flags&NQ;
}while(f==ARRAY);
alt=falign(t);
if(zlleq(al,alt)) return alt; else return al;
}
if(f==UNION||f==STRUCT){
for(i=0;i<t->exact->count;i++){
alt=falign((*t->exact->sl)[i].styp);
if(!zlleq(alt,al)) al=alt;
}
return al;
}
return al;
}
zlong szof(struct Typ *t)
/* Liefert die benoetigte Groesse eines Typs in Bytes. */
{
int i=t->flags&NQ,j;zlong size,m;
if(i<=POINTER) return sizetab[i];
if(i==ARRAY){
size=zlmult((t->size),szof(t->next));
m=align[ARRAY];
return zlmult(zldiv(zladd(size,zlsub(m,l2zl(1L))),m),m); /* align */
}
if(i==UNION){
for(j=0,size=l2zl(0L);j<t->exact->count;j++){
m=szof((*t->exact->sl)[j].styp);
if(zleqto(m,l2zl(0L))) return(l2zl(0L));
if(!zlleq(m,size)) size=m;
}
m=falign(t);
return zlmult(zldiv(zladd(size,zlsub(m,l2zl(1L))),m),m); /* align */
}
if(i==STRUCT){
for(j=0,size=0;j<t->exact->count;j++){
struct Typ *h=(*t->exact->sl)[j].styp;
m=falign(h);
size=zlmult(zldiv(zladd(size,zlsub(m,l2zl(1L))),m),m);
m=szof(h);
if(zleqto(m,l2zl(0L))) return(l2zl(0L));
size=zladd(size,m);
}
m=falign(t);
return zlmult(zldiv(zladd(size,zlsub(m,l2zl(1L))),m),m); /* align */
}
return sizetab[i];
}
void printval(FILE *f,union atyps *p,int t,int verbose)
/* Gibt atyps aus. */
{
if(t==CHAR){if(verbose)fprintf(f,"C");vlong=zc2zl(p->vchar);printzl(f,vlong);}
if(t==(UNSIGNED|CHAR)){if(verbose)fprintf(f,"UC");vulong=zuc2zul(p->vuchar);printzul(f,vulong);}
if(t==SHORT){if(verbose)fprintf(f,"S");vlong=zs2zl(p->vshort);printzl(f,vlong);}
if(t==(UNSIGNED|SHORT)){if(verbose) fprintf(f,"US");vulong=zus2zul(p->vushort);printzul(f,vulong);}
if(t==FLOAT){if(verbose)fprintf(f,"F");vdouble=zf2zd(p->vfloat);printzd(f,vdouble);}
if(t==DOUBLE){if(verbose)fprintf(f,"D");printzd(f,p->vdouble);}
if(t==INT){if(verbose)fprintf(f,"I");vlong=zi2zl(p->vint);printzl(f,vlong);}
if(t==LONG){if(verbose)fprintf(f,"L");printzl(f,p->vlong);}
if(t==(UNSIGNED|INT)){if(verbose)fprintf(f,"UI");vulong=zui2zul(p->vuint);printzul(f,vulong);}
if(t==(UNSIGNED|LONG)){if(verbose)fprintf(f,"UL");printzul(f,p->vulong);}
/* das hier ist nicht wirklich portabel */
if(t==POINTER){if(verbose)fprintf(f,"P");vulong=zp2zul(p->vpointer);printzul(f,vulong);}
}
void pric2(FILE *f,struct IC *p)
/* Gibt ein IC aus. */
{
if(p->next&&p->next->prev!=p) ierror(0);
if(p->code>=LABEL&&p->code<=BRA){
if(p->code==LABEL)
fprintf(f,"L%d",p->typf);
else{
fprintf(f,"\t%s L%d",ename[p->code],p->typf);
if(p->q1.flags){ fprintf(f,",");probj(f,&p->q1,0);}
}
}else{
fprintf(f,"\t%s ",ename[p->code]);
if(p->typf&UNSIGNED) fprintf(f,"unsigned ");
if(p->typf) fprintf(f,"%s ",typname[p->typf&NQ]);
probj(f,&p->q1,p->typf);
if(p->q2.flags){fprintf(f,",");probj(f,&p->q2,p->typf);}
if(p->z.flags){fprintf(f,"->");probj(f,&p->z,p->typf);}
if(p->code==ASSIGN||p->code==PUSH||p->code==POP) fprintf(f," size=%ld",zl2l(p->q2.val.vlong));
if((p->code==SAVEREGS||p->code==RESTOREREGS)&&p->q1.reg) fprintf(f," except %s",regnames[p->q1.reg]);
}
fprintf(f,"\n");
}
void pric(FILE *f,struct IC *p)
/* Gibt IC-Liste auf dem Bildschirm aus. */
{
while(p){
pric2(f,p);
/* if(p->q1.am||p->q2.am||p->z.am) ierror(0);*/
p=p->next;
}
}
void printzl(FILE *f,zlong x)
/* Konvertiert zlong nach ASCII. */
/* Basiert noch einigermassen auf */
/* Zweierkomplementdarstellung (d.h. -MIN>MAX). */
/* Ausserdem muss max(abs(long))<=max(unsigned long). */
{
zlong zl;zulong zul;
zl=l2zl(0L);
if(zlleq(x,zl)&&!zleqto(x,l2zl(0L))){
fprintf(f,"-");zl=zul2zl(t_max[LONG]);
if(zlleq(x,zlsub(l2zl(0L),zl))&&!zleqto(x,zlsub(l2zl(0L),zl))){
/* aufpassen, da -x evtl. >LONG_MAX */
zul=t_max[LONG];
x=zladd(x,zl);
} else zul=ul2zul(0UL);
x=zlsub(l2zl(0L),x);
vulong=zl2zul(x);
zul=zuladd(zul,vulong);
}else zul=zl2zul(x);
printzul(f,zul);
}
void printzul(FILE *f,zulong x)
/* Konvertiert zulong nach ASCII. */
{
zulong zul;unsigned long l;
zul=ul2zul(10UL);
if(!zuleqto(zuldiv(x,zul),ul2zul(0UL))) printzul(f,zuldiv(x,zul));
zul=zulmod(x,zul);l=zul2ul(zul);
fprintf(f,"%c",(int)(l+'0'));
}
void printzd(FILE *f,zdouble x)
/* Konvertiert zdouble nach ASCII, noch nicht fertig. */
{
fprintf(f,"fp-constant");
}
void *mymalloc(size_t size)
/* Belegt Speicher mit Abfrage. */
{
void *p;static int safe;
/* Um ein Fehlschlagen bei size==0 zu vermeiden; nicht sehr schoen, */
/* aber das einfachste... */
if(size==0) size=1;
if(!(p=malloc(size))){
error(12);
raus();
}
return(p);
}
void probj(FILE *f,struct obj *p,int t)
/* Gibt Objekt auf Bildschirm aus. */
{
if(p->am) ierror(0);
if(p->flags&DREFOBJ) fprintf(f,"(");
if(p->flags&VARADR) fprintf(f,"#");
if(p->flags&VAR) {
printval(f,&p->val,LONG,1);
if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
if(p->flags®)
fprintf(f,"+%s",regnames[p->reg]);
else
fprintf(f,"+%ld(FP)", zl2l(p->v->offset));
}else{
if(p->v->storage_class==STATIC){
fprintf(f,"+L%ld",zl2l(p->v->offset));
}else{
fprintf(f,"+_%s",p->v->identifier);
}
}
fprintf(f,"(%s)",p->v->identifier);
if(p->v->reg) fprintf(f,":%s",regnames[p->v->reg]);
}
if((p->flags®)&&!(p->flags&VAR)) fprintf(f,"%s",regnames[p->reg]);
if(p->flags&KONST){
fprintf(f,"#");printval(f,&p->val,t&NU,1);
}
if(p->flags&DREFOBJ) fprintf(f,")");
}
void prl(FILE *o,struct struct_declaration *p)
/* Gibt eine struct_declaration auf dem Bildschirm aus. */
{
int i;
for(i=0;i<p->count;i++) {fprintf(o," %d.:",i); prd(o,(*p->sl)[i].styp);}
}
void prd(FILE *o,struct Typ *p)
/* Gibt einen Typ auf dem Bildschirm aus. */
{
int f;
if(!p) {fprintf(o,"empty type ");return;}
f=p->flags;
/* fprintf(o,"(Sizeof=%ld,flags=%d)",zl2l(szof(p)),f);*/
/* if(type_uncomplete(p)) {fprintf(o,"incomplete ");}*/
if(f&CONST) {fprintf(o,"const ");f&=~CONST;}
if(f&STRINGCONST) {fprintf(o,"string-const ");f&=~STRINGCONST;}
if(f&VOLATILE) {fprintf(o,"volatile ");f&=~VOLATILE;}
if(f&UNSIGNED) {fprintf(o,"unsigned ");f&=~UNSIGNED;}
if(f==FUNKT){
fprintf(o,"function with parameters (");
prl(o,p->exact);
fprintf(o,") returning ");prd(o,p->next);return;
}
if(f==STRUCT){
fprintf(o,"struct with components {");
prl(o,p->exact);fprintf(o,"} ");
return;
}
if(f==UNION){
fprintf(o,"union with components {");
prl(o,p->exact);fprintf(o,"} ");
return;
}
if(f==POINTER) {fprintf(o,"pointer to ");prd(o,p->next);return;}
if(f==ARRAY) {fprintf(o,"array [size %ld] of ",zl2l(p->size));prd(o,p->next);return;}
fprintf(o,"%s",typname[f]);
}
void insert_const2(union atyps *p,int t)
/* Traegt Konstante in entprechendes Feld ein. */
{
if(!p) ierror(0);
t&=NU;
if(t==CHAR) {p->vchar=vchar;return;}
if(t==SHORT) {p->vshort=vshort;return;}
if(t==INT) {p->vint=vint;return;}
if(t==LONG) {p->vlong=vlong;return;}
if(t==(UNSIGNED|CHAR)) {p->vuchar=vuchar;return;}
if(t==(UNSIGNED|SHORT)) {p->vushort=vushort;return;}
if(t==(UNSIGNED|INT)) {p->vuint=vuint;return;}
if(t==(UNSIGNED|LONG)) {p->vulong=vulong;return;}
if(t==FLOAT) {p->vfloat=vfloat;return;}
if(t==DOUBLE) {p->vdouble=vdouble;return;}
if(t==POINTER) {p->vpointer=vpointer;return;}
}
void eval_const(union atyps *p,int t)
/* Weist bestimmten globalen Variablen Wert einer CEXPR zu. */
{
int f=t&NQ;
if(!p) ierror(0);
if(f>=CHAR&&f<=LONG){
if(!(t&UNSIGNED)){
if(f==CHAR) vlong=zc2zl(p->vchar);
if(f==SHORT)vlong=zs2zl(p->vshort);
if(f==INT) vlong=zi2zl(p->vint);
if(f==LONG) vlong=p->vlong;
vulong=zl2zul(vlong);
vdouble=zl2zd(vlong);
}else{
if(f==CHAR) vulong=zuc2zul(p->vuchar);
if(f==SHORT)vulong=zus2zul(p->vushort);
if(f==INT) vulong=zui2zul(p->vuint);
if(f==LONG) vulong=p->vulong;
vlong=zul2zl(vulong);
vdouble=zul2zd(vulong);
}
vpointer=zul2zp(vulong);
}else{
if(f==POINTER){
vulong=zp2zul(p->vpointer);
vlong=zul2zl(vulong);vdouble=zul2zd(vulong);
}else{
if(f==FLOAT) vdouble=zf2zd(p->vfloat); else vdouble=p->vdouble;
vlong=zd2zl(vdouble);
vulong=zl2zul(vlong);
}
}
vfloat=zd2zf(vdouble);
vuchar=zul2zuc(vulong);
vushort=zul2zus(vulong);
vuint=zul2zui(vulong);
vchar=zl2zc(vlong);
vshort=zl2zs(vlong);
vint=zl2zi(vlong);
}
struct function_info *new_fi(void)
/* Belegt neue function_info-Struktur und initialisiert sie. */
{
struct function_info *new;
new=mymalloc(sizeof(*new));
new->first_ic=new->last_ic=0;
new->vars=0;
new->inline_asm=0;
new->translation_unit=0;
new->used=new->modified=new->calls=0;
return new;
}
void free_fi(struct function_info *p)
/* Gibt ein function_info mit Inhalt frei. */
{
if(p->first_ic) free_IC(p->first_ic);
if(p->vars) free_var(p->vars);
free(p->calls);
free(p->used);
free(p->modified);
free(p->inline_asm);
free(p);
}